﻿using DocumentBuilderServer.Dtos;
using JMS.Token;
using System.Collections.Concurrent;
using Way.Lib;
using WebSocketUploadFile;

namespace DocumentBuilderServer.Infrastructures
{
    public class UploadHandler : IUploadFileHandler
    {
        TokenClient _tokenClient;
        IWebHostEnvironment _webHostEnvironment;
        public ConcurrentDictionary<int, FileWriter> UploadingDict = new ConcurrentDictionary<int, FileWriter>();
        public UploadHandler(IWebHostEnvironment webHostEnvironment, TokenClient tokenClient)
        {
            this._tokenClient = tokenClient;
            this._webHostEnvironment = webHostEnvironment;
            var root = Path.Combine(_webHostEnvironment.WebRootPath, "docs");
            if (Directory.Exists(root) == false)
            {
                Directory.CreateDirectory(root);
            }
            DeleteObject();
        }

        async void DeleteObject()
        {
            while (true)
            {
                await Task.Delay(600000);
                foreach(var pair in UploadingDict)
                {
                    if( (DateTime.Now - pair.Value.CreateTime).TotalHours >= 1)
                    {
                        if(UploadingDict.TryRemove(pair.Key , out FileWriter o))
                        {
                            o.Dispose();
                        }
                    }
                }
            }
        }

        public void OnBeginUploadFile(UploadHeader header, bool isContinue)
        {
            _tokenClient.Verify(header.Auth);
            var state = header.State.FromJson<UploadState>();

            if(isContinue && UploadingDict.ContainsKey(header.TranId.Value) == false)
            {
                throw new Exception("not found");
            }

            var root = Path.Combine(_webHostEnvironment.WebRootPath, "docs" , state.DocId.ToString() , "imgs");
            if (Directory.Exists(root) == false)
            {
                Directory.CreateDirectory(root);
            }

            string filepath = null;
            string path = null;
            if (!isContinue)
            {
                path = Guid.NewGuid().ToString("N") + Path.GetExtension(header.FileName);
                filepath = Path.Combine(root, path);                
            }

            var fs = UploadingDict.GetOrAdd(header.TranId.Value, k =>new FileWriter( File.OpenWrite(filepath) , path));
            if(isContinue)
            {
                fs.Stream.Seek(header.Position, SeekOrigin.Begin);
            }
        }

        public void OnError(UploadHeader header)
        {
           
        }

        public void OnReceivedFileContent(UploadHeader header, byte[] data, int length, long filePosition)
        {
            var fs = UploadingDict[header.TranId.Value];
            fs.Stream.Write(data, 0, length);
        }

        public void OnUploadCompleted(UploadHeader header)
        {
            var fs = UploadingDict[header.TranId.Value];
            fs.Dispose();
        }
    }
}
